﻿using ConfigInfoWebPlatform.API.BusinessCommon;
using ConfigInfoWebPlatform.API.DBCommon;
using ConfigInfoWebPlatform.API.HubMessage;
using ConfigInfoWebPlatform.API.ViewModel;
using ConfigInfoWebPlatform.Model;
using ConfigInfoWebPlatform.Model.Model;
using ConfigInfoWebPlatform.Nlog;
using FileSecretAssemblyStandard;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using System.Xml.Linq;

namespace ConfigInfoWebPlatform.API.Controllers
{
    /// <summary>
    /// 流程处理控制
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class MoudleCfgFileController : ControllerBase
    {
        readonly LogHelper _log;
        readonly string configRootPath;
        readonly string initDB;
        readonly InterfaceFileSecret FileSecret;
        readonly HubMessageServer hubMessageServer;
        private string backupRootPath;
        /// <summary>
        /// 流程处理控制
        /// </summary>
        public MoudleCfgFileController(LogHelper logHelper, IConfiguration configuration, InterfaceFileSecret fileSecret,HubMessageServer hubMessage)
        {
            _log = logHelper;
            configRootPath = configuration["AppSetting:configPath"].ToString();
            backupRootPath = configRootPath.Replace("wordparse2.0", "备份");
            initDB = configuration["AppSetting:initDB"].ToString();
            FileSecret = fileSecret;
            hubMessageServer = hubMessage;
        }
        /// <summary>
        /// 根据文件路径获取文件信息
        /// </summary>
        /// <param name="dir"></param>
        /// <param name="page"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        [HttpGet("index")]
        public JsonResult Index(string dir, int page, int limit)
        {
            var fpath = Request.Query["fpath"];
            var fnote = Request.Query["fnote"];
            var fname = Request.Query["fname"];
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取用户角色操作权限
            DAL_Role dal_Role = new DAL_Role();
            var isOperate = dal_Role.GetOperateAuthorityByRid(user.R_id);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            string filepath = Path.Combine(configRootPath, versionPath, dir).Replace("\\", "/");
            if (!Directory.Exists(filepath))
            {
                Directory.CreateDirectory(filepath);
            }
            // 配置文件总列表
            ConfigFileList configFileList = new ConfigFileList();
            // 流程配置文件信息
            List<ConfigFileInfoModel> moduleCfgFileInfos = new List<ConfigFileInfoModel>();

            // 获取导航功能ID
            DAL_ProgramNavicat navicat = new DAL_ProgramNavicat();
            ProgramNavicatModel program = navicat.GetProgramNavicatInfoByDir(dir);
            long programid = Convert.ToInt64(program.ID);
            string moudleCode = program.Code;

            // 获取流程配置的文件结构
            DAL_ConfigFile configFile = new DAL_ConfigFile();
            moduleCfgFileInfos = configFile.GetConfigFiles(programid);
            //UpdataModuelRemark(moduleCfgFileInfos);
            if (!string.IsNullOrWhiteSpace(fname))
                moduleCfgFileInfos = moduleCfgFileInfos.Where(x => x.name.Contains(fname)).ToList();
            if (!string.IsNullOrWhiteSpace(fpath))
                moduleCfgFileInfos = moduleCfgFileInfos.Where(x => x.path.Contains(fpath)).ToList();

            if (!string.IsNullOrWhiteSpace(fnote))
                moduleCfgFileInfos = moduleCfgFileInfos.Where(x => !string.IsNullOrWhiteSpace(x.note) && x.note.Contains(fnote)).ToList();


            if (moduleCfgFileInfos != null && moduleCfgFileInfos.Count > 0)
            {
                configFileList.processCfgFiles = moduleCfgFileInfos.Where(a => a.ctype == "F" && a.name.IndexOf("索引") < 0 && a.name.IndexOf("Index") < 0 && (!a.name.Contains("back"))).ToList();
            }
            else
            {
                configFileList.processCfgFiles = moduleCfgFileInfos;
            }
            List<ConfigFileInfoModel> re = new List<ConfigFileInfoModel>();
            // 获取页面的数据
            if (configFileList.processCfgFiles != null && configFileList.processCfgFiles.Count > 0)
            {
                re = configFileList.processCfgFiles.Skip((page - 1) * limit).Take(limit).ToList();
            }
            return new JsonResult(new { code = 0, msg = "success", count = configFileList.processCfgFiles.Count, data = re, moudleCode = moudleCode, isOperate = user.Name == "admin" ? 1 : isOperate });
        }

        [HttpPost("saveFile")]
        public JsonResult SaveFile(string dir)
        {
            string fileName = Request.Form["filename"].ToString();
            try
            {
                //获取用户信息
                UserInfoModel user = new UserInfoModel();
                var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
                user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
                DAL_UserInfo userDal = new DAL_UserInfo();
                string rid = userDal.GetUserRid(user.Id);
                //获取版本信息
                VersionModel version = new VersionModel();
                var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
                version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
                var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
                
                //string type = Request.Form["type"];
                string explain = Request.Form["explain"].ToString();
                string MLFlag = string.IsNullOrWhiteSpace(Request.Form["MLFlag"].ToString()) ? "0" : Request.Form["MLFlag"].ToString();
                string type=string.IsNullOrWhiteSpace(Request.Form["type"].ToString()) ? "0" : Request.Form["type"].ToString();

                string fileParentdir = dir.Replace("\\", @"/");
                string fileParentPath = fileParentdir;
                if (string.IsNullOrEmpty(fileName))
                {
                    return new JsonResult("err请输入文件名");
                }
                //保存的XML的地址
                if (fileName.IndexOf(".") > -1)
                {
                    fileName = fileName.Substring(0, fileName.IndexOf(".")) + ".xml";
                }
                else
                {
                    fileName = fileName + ".xml";
                }
                string fullpath = Path.Combine(configRootPath, versionPath, fileParentPath, fileName).Replace("\\", @"/");

                string XMLPath = fullpath;
                if (System.IO.File.Exists(XMLPath))
                {
                    _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgFileController--SaveFile方法：模块配置文件" + fileName + "已经存在!");
                    return new JsonResult("err文件已经存在");
                }
                else
                {
                    XmlDocument xmlDoc = new XmlDocument();
                    XmlNode node = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "");
                    xmlDoc.AppendChild(node);
                    XmlNode root = xmlDoc.CreateElement("root");
                    xmlDoc.AppendChild(root);
                    XmlAttribute xAttributeType = xmlDoc.CreateAttribute("type");
                    xAttributeType.Value = type;
                    XmlAttribute xAttributeExplain = xmlDoc.CreateAttribute("explain");
                    xAttributeExplain.Value = explain;
                    XmlAttribute xmlAttributeMLFlag = xmlDoc.CreateAttribute("mlflag");
                    xmlAttributeMLFlag.Value = MLFlag;
                    if(dir.Contains("2docsubsection"))
                    {
                        root.Attributes.Append(xmlAttributeMLFlag);
                        root.Attributes.Append(xAttributeType);
                    }
                    
                    root.Attributes.Append(xAttributeExplain);
                    FileSecret.EncryptContentToFile(xmlDoc.OuterXml, XMLPath);
                    xmlDoc.Save(XMLPath);
                    SaveFileInfoToDb(XMLPath, fileParentPath, fileName, explain);
                    _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgFileController--SaveFile方法：模块配置文件" + XMLPath + "保存成功!");
                    _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}保存模块配置文件{XMLPath}成功!");
                    RefreshStatistics(user.Name, rid);
                    return new JsonResult("success");
                }
            }
            catch (Exception ex)
            {
                _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgFileController--SaveFile方法：添加文件" + fileName + "异常："+ex.Message);
            }
            return new JsonResult("success");
        }


        /// <summary>
        /// 上传文件
        /// </summary>
        /// <returns>上传文件结果信息</returns>
        [HttpPost("uploadfile")]
        public ActionResult UploadFile()
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            DAL_UserInfo userDal = new DAL_UserInfo();
            string rid = userDal.GetUserRid(user.Id);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            Result re = new Result();
            string dir = Request.Form["dir"].ToString();
            // 上传文件中，faildFiles表示上传失败的文件名，successFiles表示上传成功的文件名
            List<string> faildFiles = new List<string>();
            List<string> successFiles = new List<string>();
            // 上传失败的数量
            int failedNum = 0;
            try
            {
                var files = Request.Form.Files;
                string fileParentdir = dir.Replace("\\", "/");
                string describe = "";
                for (int i = 0; i < files.Count; i++)
                {
                    _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-UploadFile方法：上传的文件是" + files[i].FileName);
                    string filename = Path.GetFileName(files[i].FileName);
                    string fileParentPath = fileParentdir;
                    string fullpath = Path.Combine(configRootPath, versionPath, fileParentPath, "_" + filename);
                    string absolutePath= Path.Combine(configRootPath, versionPath, fileParentPath, filename).Replace("\\","/");
                    string backPath = Path.Combine(backupRootPath, versionPath, fileParentPath, filename).Replace("\\", "/");
                    if (System.IO.File.Exists(absolutePath))
                    {
                        _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-UploadFile方法：上传的文件" + filename + "已经存在！");
                        // 这里要判断一下是否文件的后缀名，如果是dll，要删除旧文件，保存新文件；同时要在dlls文件夹下创建新的版本目录
                        string extensionName = Path.GetExtension(fullpath);
                        if (extensionName == ".dll")
                        {
                            // 删除模块下旧的文件，保存新的文件
                            System.IO.File.Delete(fullpath);
                            FileStream fileStream = new FileStream(fullpath, FileMode.CreateNew);
                            files[i].CopyTo(fileStream);
                            fileStream.Close();
                            //files[i].SaveAs(filename);
                            // 拼接成dll各个版本的存储目录
                            try
                            {
                                // 应用目录
                                DirectoryInfo appDir = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
                                string fileN = Path.GetFileName(fullpath);
                                string rootPath = !string.IsNullOrWhiteSpace(versionPath) ? $"{configRootPath}/{versionPath}" : configRootPath;
                                string dllPath = rootPath + @"/config/dlls/" + fileN.Substring(0, fileN.Length - 4);
                                // 生成新的版本文件
                                string versionNo = DateTime.Now.ToString("yyyyMMddHHmmss");
                                Directory.CreateDirectory(Path.Combine(dllPath, versionNo));
                                System.IO.File.Copy(filename, Path.Combine(dllPath, versionNo, Path.GetFileName(fullpath)));
                                // 根据描述信息生成描述文件
                                CreateDescribeFile(dllPath, versionNo, describe);
                                successFiles.Add(filename);
                                _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}在{fileParentPath}下上传文件{Path.GetFileName(files[i].FileName)}");
                            }
                            catch (Exception ex)
                            {
                                _log.WriteLog(LogHelper.logType.Error, "MoudleCfgController-UploadFile方法：" + fullpath + "上传失败!错误信息" + ex.Message);
                            }
                        }
                        else
                        {

                            FileInfo fi = new FileInfo(absolutePath);
                            if (!Directory.Exists(Path.GetDirectoryName(backPath)))
                                Directory.CreateDirectory(Path.GetDirectoryName(backPath));
                            fi.MoveTo(backPath + "back" + DateTime.Now.ToString("yyyyMMddHHmmss"));
                            //fi.MoveTo(absolutePath + "back" + DateTime.Now.ToString("yyyyMMddHHmmss"));
                            FileStream fileStream = new FileStream(fullpath, FileMode.CreateNew);
                            files[i].CopyTo(fileStream);
                            fileStream.Close();
                            this.EncryptFileToFile(fullpath, absolutePath);
                            _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}在{fileParentPath}下替换文件{Path.GetFileName(files[i].FileName)}");
                            System.IO.File.Delete(fullpath);
                            successFiles.Add(filename);
                            SaveFileInfoToDb(absolutePath, fileParentPath, filename, describe);

                        }
                    }
                    else
                    {
                        //文件相对路径
                        string fileRelativePath = fileParentPath;

                        FileStream fileStream = new FileStream(fullpath, FileMode.CreateNew);
                        files[i].CopyTo(fileStream);
                        fileStream.Close();
                        //files[i].SaveAs(filename);
                        var enfilename = Path.Combine(configRootPath, versionPath, fileParentPath, filename).Replace("\\", "/");
                        this.EncryptFileToFile(fullpath, enfilename);
                        string versionNo = DateTime.Now.ToString("yyyyMMddHHmmss");
                        string extensionName = Path.GetExtension(fullpath);
                        if (extensionName == ".dll")
                        {
                            string fileN = Path.GetFileName(fullpath);
                            string rootPath = !string.IsNullOrWhiteSpace(versionPath) ? $"{configRootPath}/{versionPath}" : configRootPath;
                            string dllPath = rootPath + @"/config/dlls/" + fileN.Substring(0, fileN.Length - 4);
                            // 首次上传生成版本目录

                            Directory.CreateDirectory(Path.Combine(dllPath, versionNo));
                            System.IO.File.Copy(fullpath, Path.Combine(dllPath, versionNo, Path.GetFileName(fullpath)));
                            // 根据描述信息生成描述文件
                            CreateDescribeFile(dllPath, versionNo, describe);
                        }

                        _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-UploadFile方法：" + fullpath + "上传成功!");
                        _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}在{fileParentPath}下上传文件{filename}");
                        successFiles.Add(filename);
                        System.IO.File.Delete(fullpath);
                        SaveFileInfoToDb(enfilename, fileParentPath, filename, describe);
                    }

                }
                var failMsg = faildFiles.Count > 0
                            ? $"{string.Join(",", faildFiles)}"
                            : string.Empty;
                var successMsg = successFiles.Count > 0
                               ? $"{string.Join(",", successFiles)}上传成功"
                               : string.Empty;
                re.message = faildFiles.Count > 0
                           ? $"{failMsg},{successMsg}"
                           : successMsg;
                re.code = "1";
                RefreshStatistics(user.Name, rid);
            }
            catch (Exception e)
            {
                _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-UploadFile方法：出现异常" + e.Message);
                re.code = "0";
                re.message = e.Message;
            }
            return new JsonResult(re);
        }

        /// <summary>
        /// 删除配置文件
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <returns></returns>
        [HttpPost("delfile")]
        public ActionResult DelFile(string fileName)
        {
            // 获取流程配置的文件结构
            //string processConfigPath = configRootPath;
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            DAL_UserInfo userDal = new DAL_UserInfo();
            string rid = userDal.GetUserRid(user.Id);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            string fileNameFull = Path.Combine(configRootPath, versionPath, fileName).Replace("\\", "/");
            if (System.IO.File.Exists(fileNameFull))
            {

                // 数据中删除该文件的记录
                fileName = fileName.Replace("\\", "/");
                _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-DelFile方法：删除文件" + fileName + "数据库记录");
                DAL_ConfigFile configFileDal = new DAL_ConfigFile();
                DAL_ProgramNavicat navicatDal = new DAL_ProgramNavicat();
                var configFileInfo = configFileDal.GetConfigFileByPath(fileName);
                if (configFileDal.ExistFile(fileName) > 0)
                {
                    configFileDal.DeleteConfigFile(fileName);
                    var nav = navicatDal.GetNavicatById(configFileInfo.Programid.Value);
                    if (nav != null)
                    {
                        DAL_MenuStatistics statisticsDal = new DAL_MenuStatistics();
                        //修改当前菜单文件数量
                        statisticsDal.FileNumDecrement(nav.Id);

                        //修改父级菜单文件数量
                        var allParentId = nav.AllParentId;
                        if (!string.IsNullOrWhiteSpace(allParentId))
                        {
                            List<string> parentids = allParentId.Split(",").Reverse().ToList();
                            foreach (var id in parentids)
                            {
                                long navId = Int64.Parse(id);
                                statisticsDal.FileNumDecrement(navId);
                            }
                        }
                    }
                    RefreshStatistics(user.Name, rid);
                }

                /* 删除模块配置文件需要从当前模块下找到index索引文件，根据索引找到调用被模块配置的流程配置文件，
                之后打开流程配置文件，删除该模块配置文件的步骤*/

                // 打开索引文件，获取index节点
                _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-DelFile方法：开始修改索引文件!");
                string dirName = Path.GetDirectoryName(fileNameFull);
                string modefile = Path.GetFileName(fileName);
                string indexFileName = dirName + @"\Index.xml";
                if (System.IO.File.Exists(indexFileName))
                {
                    string content = FileSecret.DecryptFileToContent(indexFileName);
                    XDocument xDocument = XDocument.Parse(content);
                    var reNodes = xDocument.Element("root").Elements().ToList();

                    // 遍历index节点，获取processfile属性中关联的流程配置文件
                    _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-DelFile方法：遍历索引文件modefile=" + modefile + "的节点。");
                    List<XElement> filteredNodes = reNodes.Where(a => a.Attribute("modefile").Value == modefile).ToList();
                    foreach (XElement item in filteredNodes)
                    {
                        // 打开流程配置文件
                        string processCfgFile = item.Attribute("processfile").Value;
                        // 解密文件加载到XDocument
                        string fileContent = FileSecret.DecryptFileToContent($"{configRootPath}/{versionPath}/{processCfgFile}");
                        XDocument processCfgXml = XDocument.Parse(fileContent);
                        var stepNodes = xDocument.Element("root").Elements().ToList();
                        _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-DelFile方法：根据索引文件的配置信息找到流程配置文件" + processCfgFile);

                        // 找到当前模块配置文件在流程配置文件中的节点
                        List<XElement> filteredStepNodes = stepNodes.Where(a => a.Attribute("executefile").Value == modefile).ToList();
                        foreach (XElement node in filteredStepNodes)
                        {
                            // 删除流程配置文件中当前模块配置的节点
                            node.Remove();
                            _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-DelFile方法：遍历流程配置文件中的step节点删除executefile=" + modefile + "的节点。");
                            _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy - MM - dd HH: mm:ss")}用户{user.Name}遍历流程配置文件中的step节点删除executefile={modefile}的节点");
                        }
                        processCfgXml.Save($"{configRootPath}/{versionPath}/{processCfgFile}");
                    }
                    _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-DelFile方法：未找到索引文件" + indexFileName);
                }
                else
                {
                    _log.WriteLog(LogHelper.logType.Error, "MoudleCfgController-DelFile方法：未找到索引文件" + indexFileName);
                }
                // 对要删除的文件重命名
                string backPath = Path.Combine(backupRootPath, versionPath, fileName);
                FileInfo fi = new FileInfo(fileNameFull);
                if (!Directory.Exists(Path.GetDirectoryName(backPath)))
                    Directory.CreateDirectory(Path.GetDirectoryName(backPath));
                fi.MoveTo(backPath + "back" + DateTime.Now.ToString("yyyyMMddHHmmss"));
                _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-DelFile方法：删除" + fileName + "文件！系统将该文将重命名为" + fileName + "back" + DateTime.Now.ToString("yyyyMMddHHmmss"));
                _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}删除了{fileName}文件");
            }

            return new JsonResult(new { code = 1, msg = "删除成功" });
        }


        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <returns></returns>
        [HttpGet("downloadfile")]
        public ActionResult DownLoadFile(string fileName)
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            Result re = new Result();
            if (!string.IsNullOrEmpty(fileName))
            {
                re.code = "1";
                string filenameTemp = Path.Combine(configRootPath, versionPath, fileName).Replace("\\", "/");
                string clientFileName = Path.GetFileName(fileName);
                string fileContent = FileSecret.DecryptFileToContent(filenameTemp);
                byte[] bytes = Encoding.UTF8.GetBytes(fileContent);
                //二进制流数据（如常见的文件下载）
                return File(bytes, "application/octet-stream", clientFileName);
            }
            else
            {
                re.code = "0";
                re.message = "下载失败";
                return BadRequest(re);
            }
        }

        /// <summary>
        /// 查看指定配置文件的具体内容
        /// </summary>
        /// <param name="fileName">文件全路径</param>
        /// <param name="moduleCode">模块编号</param>
        /// <returns></returns>
        [HttpGet("detail")]
        public ActionResult Detail(string fileName, string moudleCode)
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取用户角色操作权限
            DAL_Role dal_Role = new DAL_Role();
            var isOperate = dal_Role.GetOperateAuthorityByRid(user.R_id);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            ParseConfigFile parseConfigFile = new ParseConfigFile(new DAL_ProgramNavicat(), new DAL_ConfigFile(), initDB, FileSecret);
            List<ModuleConfig> moduleConfigs = new List<ModuleConfig>();
            string fileInfoFull = Path.Combine(configRootPath, versionPath, fileName).Replace("\\", "/");
            FileInfo fileInfo = new FileInfo(fileInfoFull);
            var stepNo = "1";

            // 读取模块必要节点配置
            string mustNodepath = Path.Combine(System.Environment.CurrentDirectory, "MustNode.json");
            string jsonStr = System.IO.File.ReadAllText(mustNodepath);
            var fileNameArry = fileName.Split('/');
            //是否卷宗分段
            var isSection = false;
            if (fileNameArry.Contains("2docsubsection"))
                isSection = true;

            // 获取模块必要节点集合
            MustNodeModel mustNodeList = System.Text.Json.JsonSerializer.Deserialize<MustNodeModel>(jsonStr);
            Mustnode mustNode = mustNodeList.MustNodes.FirstOrDefault(x => x.moudleCode.ToLower() == moudleCode.ToLower());
            List<string> mustStepCodes = new List<string>();
            if (mustNode != null && mustNode.moudleSteps != null)
            {
                mustStepCodes = mustNode.moudleSteps.Where(x => !string.IsNullOrWhiteSpace(x.moudleStepCode)).Select(x => x.moudleStepCode).ToList();
            }
            string nodeTip = string.Empty;
            bool mlflag = false;
            bool type = false;
            if (System.IO.File.Exists(fileInfoFull) && fileInfo.Length > 0)
            {
                // 解密文件，展示文件内容
                try
                {
                    string xmlContent = FileSecret.DecryptFileToContent(fileInfoFull);
                    XmlDocument doc = new XmlDocument();
                    doc.LoadXml(xmlContent);
                    XmlNodeList nodelist = doc.SelectNodes("/root");
                    XmlNode rootNode = nodelist[0];
                    var mlflagAttr = rootNode.Attributes["mlflag"];
                    if (mlflagAttr != null)
                    {
                        int outMlflag = 0;
                        int.TryParse(mlflagAttr.Value, out outMlflag);
                        mlflag = outMlflag == 1 ? true : false;
                    }
                        
                    var typeAttr = rootNode.Attributes["type"];
                    if (typeAttr != null)
                    {
                        int outType = 0;
                        int.TryParse(typeAttr.Value, out outType);
                        type = outType == 1 ? true : false;
                    }


                    moduleConfigs = parseConfigFile.parseXmlMoudleConfig(doc, "", fileName);

                    if (moduleConfigs != null && moduleConfigs.Count > 0)
                    {
                        var moduleConfig = moduleConfigs.OrderByDescending(x => Convert.ToDouble( x.number)).FirstOrDefault();
                        stepNo = (Convert.ToDouble(moduleConfig.number) + 1).ToString();
                        List<string> configured = moduleConfigs.Select(x => x.code).ToList();
                        if (mustStepCodes.Any())
                        {
                            List<string> lacks = mustStepCodes.Except(configured).ToList();
                            if (lacks != null && lacks.Any())
                                nodeTip = $"当前模块缺少步骤编号为{string.Join('、', lacks)}的配置,请及时配置";
                        }
                    }
                    else
                    {
                        if (mustStepCodes.Any())
                            nodeTip = $"当前模块缺少步骤编号为{string.Join('、', mustStepCodes)}的配置,请及时配置";
                    }
                }
                catch (Exception ex)
                {
                    _log.WriteLog(LogHelper.logType.Error, "分析模块Detail出现异常:" + ex.Message);
                }
            }
            var isAdmin = user.Name == "admin" ? 1 : isOperate;

            object result = null;
            if(isSection)
            {
                result = new
                {
                    code = 0,
                    msg = "success",
                    stepNo = stepNo,
                    count = moduleConfigs.Count,
                    data = moduleConfigs,
                    nodeTip = nodeTip,
                    isOperate = isAdmin,
                    isSection=isSection,
                    mlflag=mlflag,
                    type=type
                };
            }
            else
            {
                result = new
                {
                    code = 0,
                    msg = "success",
                    stepNo = stepNo,
                    count = moduleConfigs.Count,
                    data = moduleConfigs,
                    nodeTip = nodeTip,
                    isOperate = isAdmin,
                    isSection = isSection,
                };
            }

            return new JsonResult(result);
        }

        /// <summary>
        /// 删除流程配置文件中的某一项
        /// </summary>
        [HttpPost("deleteitem")]
        public ActionResult DeleteItem()
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            string fileP = "",         //保存流程配置文件的绝对路径的明文
                   moduleCfgFilePath = ""; //模块配置文件的路径，根据这个路径找到索引文件
            // 获取请求过来的json数据
            var sr = new StreamReader(Request.Body);
            var strcontent = sr.ReadToEnd();
            sr.Close();
            // 将json数据转成对应的实体
            DelProcessCfgFileItemModel delItemInfo = new DelProcessCfgFileItemModel();
            delItemInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<DelProcessCfgFileItemModel>(strcontent);
            moduleCfgFilePath = Base64Helper.DeCodeBase64(65001, delItemInfo.moduleFile).Replace("/", @"\");
            // 解密文件路径
            fileP = Base64Helper.DeCodeBase64(65001, delItemInfo.filePath);
            //文件模块路径
            string filePTemp = Path.Combine(configRootPath, versionPath, moduleCfgFilePath).Replace("\\", "/");
            if (System.IO.File.Exists(filePTemp))
            {
                FileInfo fileInfo = new FileInfo(filePTemp);
                if (fileInfo.Length > 0)
                {
                    // 读取配置文件，并查找到number=json数据传过来的number，之后删除查找到的节点
                    string fileContent = FileSecret.DecryptFileToContent(filePTemp);
                    XDocument xdocument = XDocument.Parse(fileContent);
                    var reNodes = xdocument.Element("root").Elements().ToList();
                    if (delItemInfo.number.IndexOf(".") > -1)
                    {
                        //序号切片，得到父子级组合
                        string[] nodelist = delItemInfo.number.Split('.');
                        string parentNum = "";
                        List<XElement> xElements = new List<XElement>();
                        xElements = reNodes;
                        for (int loops = 1; loops <= nodelist.Length; loops++)
                        {
                            if (loops < nodelist.Length)
                            {
                                parentNum = CommonHandle.Arra_cut(nodelist, 0, loops, ".");
                                List<XElement> filterRe = xElements.Where(a => a.Attribute("number").Value == parentNum).ToList();
                                xElements = filterRe[0].Elements().ToList();
                            }
                            else
                            {
                                List<XElement> filterRe = xElements.Where(a => a.Attribute("number").Value == delItemInfo.number).ToList();
                                filterRe[0].Remove();
                            }
                        }
                    }
                    else
                    {
                        List<XElement> filterRe = reNodes.Where(a => a.Attribute("number").Value == delItemInfo.number).ToList();
                        filterRe[0].Remove();
                    }
                    // 保存配置文件
                    FileSecret.EncryptContentToFile(xdocument.ToString(), filePTemp);
                    var delFileName = Path.GetFileName(fileP);
                    _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgFileController--DeleteItem方法：模块配置文件" + fileP + "number=" + delItemInfo.number + "被删除了!");
                    _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy - MM - dd HH: mm:ss")}用户{user.Name}删除了模块配置文件{moduleCfgFilePath}中number={delItemInfo.number}执行代码为{delFileName}的配置项!");
                }
            }
            return new JsonResult("删除成功！");
        }

        /// <summary>
        /// 保存修改的配置文件
        /// </summary>
        /// <returns></returns>
        [HttpPost("uploadfileofitem")]
        public ActionResult UploadFileOfItem()
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            //ViewBag.fileName = Request.Form["moduleCfgName"];
            StepF moduleCfgItemInfo = new StepF();
            //{"moduleCfgName":"@ViewBag.fName","oldNumber":"1","number":"1","executeType":"reg","executeFile":"MS_CR_Header","executeCode":"","code":"MS_CR_Header","zh_cn":"首部"}
            moduleCfgItemInfo.fileName = Request.Form["moduleCfgName"];
            moduleCfgItemInfo.number = Request.Form["number"];
            //moduleCfgItemInfo.executetype = Request.Form["executeType"];
            moduleCfgItemInfo.executetype = Request.Form["editexecuteType"];
            if (moduleCfgItemInfo.executetype == null)
            {//由于新增与编辑调用的是一个页面
                moduleCfgItemInfo.executetype = Request.Form["executeType"];
            }
            moduleCfgItemInfo.executecode = Request.Form["executeFile"];
            moduleCfgItemInfo.code = Request.Form["code"];
            moduleCfgItemInfo.zh_cn = Request.Form["zh_cn"];
            moduleCfgItemInfo.executefile = Request.Form["executeFile"];
            string oldNumer = Request.Form["oldNumber"];

            // 如果是dll文件，那么将当前这个dll的最新版本的路径放到executefile里面
            if (moduleCfgItemInfo.executetype == "dll")
            {
                moduleCfgItemInfo.executecode = Path.GetFileName(Request.Form["executeFile"]);
            }
            else if (moduleCfgItemInfo.executetype == "reg")
            {
                moduleCfgItemInfo.code = Request.Form["code"];
                moduleCfgItemInfo.executecode = Request.Form["executeFile"];
                moduleCfgItemInfo.executefile = "";
            }
            else
            {
                moduleCfgItemInfo.executecode = Path.GetFileName(Request.Form["executeFile"]);
            }
            moduleCfgItemInfo.code = moduleCfgItemInfo.code.ToLower();
            // 根据文件路径打开文件
            string fileName = Base64Helper.DeCodeBase64(65001, moduleCfgItemInfo.fileName);

            // 根据number属性找到step的节点，之后跟该节点的属性值
            string fileNameTemp = Path.Combine(configRootPath, versionPath, fileName).Replace("\\", "/");
            if (System.IO.File.Exists(fileNameTemp))
            {
                FileInfo fileInfo = new FileInfo(fileNameTemp);
                if (fileInfo.Length > 0)
                {
                    try
                    {
                        // 读取配置文件，并查找到number=json数据传过来的number，之后删除查找到的节点
                        string xmlContent = FileSecret.DecryptFileToContent(fileNameTemp);
                        XDocument xdocument = XDocument.Parse(xmlContent);
                        var reNodes = xdocument.Element("root").Elements().ToList();
                        var isExit = IsExitByCode(reNodes, oldNumer, moduleCfgItemInfo.code);
                        if(isExit)
                        {
                            return BadRequest("已存在该步骤编码的配置节点");
                        }
                        // 只要修改了序号，程序就默认的是删除旧序号的内容
                        if (!string.IsNullOrEmpty(oldNumer) && oldNumer != moduleCfgItemInfo.number)
                        {
                            reNodes = GetNodeByNumber(reNodes, oldNumer);
                            List<XElement> delNode = reNodes.Where(a => a.Attribute("number").Value == oldNumer).ToList();

                            if (delNode.Count > 0)
                                delNode[0].Remove();
                        }
                        List<XElement> filterRe = new List<XElement>();
                        foreach (XElement item in reNodes)
                        {
                            GetNodeByNumber(moduleCfgItemInfo.number, item, filterRe);
                        }

                        if (filterRe.Count == 0)
                        {
                            // 如果当前传入的节点在流程配置文件中找不到就添加节点
                            XElement newNode = new XElement("step");
                            newNode.SetAttributeValue("number", moduleCfgItemInfo.number);
                            newNode.SetAttributeValue("executefile", moduleCfgItemInfo.executefile);
                            newNode.SetAttributeValue("executetype", moduleCfgItemInfo.executetype);
                            newNode.SetAttributeValue("executecode", moduleCfgItemInfo.executecode);
                            newNode.SetAttributeValue("code", moduleCfgItemInfo.code);
                            newNode.SetAttributeValue("zh_cn", moduleCfgItemInfo.zh_cn);
                            // 添加节点
                            XElement parentNode = null;
                            if (moduleCfgItemInfo.number.Contains("."))
                            {
                                // 获取父节点的number
                                string[] parentsNumber = moduleCfgItemInfo.number.Split('.');
                                string parentNumber = "";
                                for (int i = 0; i < parentsNumber.Length - 1; i++)
                                {
                                    if (string.IsNullOrEmpty(parentNumber))
                                    {
                                        parentNumber = parentsNumber[i].ToString();
                                        parentNode = reNodes.Where(a => a.Attribute("number").Value == parentNumber).ToList()[0];
                                    }
                                    else
                                    {
                                        parentNumber += "." + parentsNumber[i];
                                        parentNode = parentNode.Elements().Where(a => a.Attribute("number").Value == parentNumber).ToList()[0];
                                    }
                                }
                                string oldBrotherNumer = parentNumber + "." + Convert.ToString(Convert.ToInt32(parentsNumber[parentsNumber.Length - 1]) - 1);
                                List<XElement> brotherNode = parentNode.Elements().Where(a => a.Attribute("number").Value == oldBrotherNumer).ToList();
                                if (brotherNode.Count > 0)
                                {
                                    // 存在兄长节点添加到兄长节点之后
                                    brotherNode[0].AddAfterSelf(newNode);
                                }
                                else
                                {
                                    // 不存在兄长节点添加到父节点之下
                                    parentNode.Add(newNode);
                                }
                            }
                            else
                            {
                                string oldBrotherNumber = Convert.ToString(Convert.ToInt32(moduleCfgItemInfo.number) - 1);
                                List<XElement> oldBrotherNode = reNodes.Where(a => a.Attribute("number").Value == oldBrotherNumber).ToList();
                                if (oldBrotherNode.Count > 0)
                                {
                                    // 存在兄长节点就添加到兄长节点之后
                                    oldBrotherNode[0].AddAfterSelf(newNode);
                                }
                                else
                                {
                                    // 无兄长节点就添加到父节点之下
                                    xdocument.Element("root").Add(newNode);
                                }
                            }
                            _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgFileController--UdpFile方法：模块配置文件" + fileName + "添加number=" + moduleCfgItemInfo.number + "的节点");
                            _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}在模块配置文件{fileName}中添加executecode={moduleCfgItemInfo.executecode}的节点");
                        }
                        else
                        {
                            // 如果当前传入的节点在流程配置文件中能找到就更新节点
                            filterRe[0].SetAttributeValue("number", moduleCfgItemInfo.number);
                            filterRe[0].SetAttributeValue("executefile", moduleCfgItemInfo.executefile);
                            filterRe[0].SetAttributeValue("executetype", moduleCfgItemInfo.executetype);
                            filterRe[0].SetAttributeValue("executecode", moduleCfgItemInfo.executecode);
                            filterRe[0].SetAttributeValue("code", moduleCfgItemInfo.code);
                            filterRe[0].SetAttributeValue("zh_cn", moduleCfgItemInfo.zh_cn);
                            _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgFileController--UdpFile方法：模块配置文件" + fileName + "number=" + moduleCfgItemInfo.number + "的节点被修改");
                            _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}在模块配置文件{fileName}中修改number={moduleCfgItemInfo.number}节点");
                        }
                        string dd = xdocument.ToString();
                        FileSecret.EncryptContentToFile(xdocument.ToString(), fileNameTemp);
                        DAL_ConfigFile dAL_ConfigFile = new DAL_ConfigFile();
                        dAL_ConfigFile.UpdateStamp(fileName);
                    }
                    catch (Exception ex)
                    {
                        _log.WriteLog(LogHelper.logType.Error, "MoudleCfgFileController--UdpFile方法：模块配置文件" + fileNameTemp + "被更新时报错,错误信息" + ex.Message);
                        return BadRequest("error，数据更新错误");
                    }
                }
            }
            return new JsonResult("success");
        }
        /// <summary>
        /// 根据number获取节点
        /// </summary>
        /// <param name="nodes">节点</param>
        /// <param name="number">序号</param>
        /// <returns></returns>
        private List<XElement> GetNodeByNumber(List<XElement> nodes, string number)
        {
            XElement parentNode = null;
            List<XElement> re = new List<XElement>();
            re = nodes;
            if (number.IndexOf(".") > -1)
            {
                string[] numbers = number.Split('.');
                List<XElement> parentNodeList = new List<XElement>();
                string childNo = "";
                for (int i = 0; i < numbers.Length; i++)
                {
                    if (i == 0)
                    {
                        childNo = numbers[i];
                    }
                    else
                    {
                        childNo += "." + numbers[i];
                    }

                    if (childNo == number)
                    {
                        XElement targetNode = re.Where(a => a.Attribute("number").Value == childNo).ToList()[0];
                        targetNode.Remove();
                    }
                    else
                    {
                        parentNodeList = re.Where(a => a.Attribute("number").Value == childNo).ToList();
                        if (parentNodeList.Count > 0)
                        {
                            parentNode = parentNodeList[0];
                            re = parentNode.Elements().ToList();
                        }
                        else
                        {
                            _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgFileController--GetNodeByNumber方法：删除节点时找不到" + childNo + "!");
                            return nodes;
                        }
                    }
                }
            }
            return nodes;
        }
        /// <summary>
        /// 根据number属性查找到节点
        /// </summary>
        /// <param name="number">number的属性值</param>
        /// <param name="node">源节点</param>
        /// <param name="targetNode">目标节点</param>
        private void GetNodeByNumber(string number, XElement node, List<XElement> targetNode)
        {
            if (node.HasElements)
            {
                foreach (XElement item in node.Elements())
                {
                    if (item.Attribute("number").Value == number)
                    {
                        // 当前的number属性是唯一的，只要找到就没有必要继续循环，所以当找到的时候就跳出循环提高代码的执行效率
                        targetNode.Add(item);
                        break;
                    }
                    if (item.Elements().Count() > 0)
                    {
                        GetNodeByNumber(number, item, targetNode);
                    }
                }
            }
            if (node.HasAttributes)
            {
                if (node.Attribute("number").Value == number)
                {
                    targetNode.Add(node);
                }
            }
        }

        private bool IsExitByCode(List<XElement> steps,string number,string code)
        {
            bool isHave = false;
            if(steps!=null && steps.Any())
            {
                int count = 0;
                if(string.IsNullOrWhiteSpace(number))
                {
                    isHave = steps.Any(x => x.Attribute("code").Value.ToLower() == code);
                }
                else
                {
                    isHave = steps.Any(x => x.Attribute("code").Value.ToLower() == code && x.Attribute("number").Value!=number);
                }
            }

            return isHave;
        }

        /// <summary>
        /// 获取dll文件最新的版本路径
        /// </summary>
        /// <param name="fileName">dll文件名</param>
        /// <returns></returns>
        private string GetDllPath(string fileName)
        {
            string fileN = fileName;
            string dllPath = configRootPath + @"\config\dlls\" + fileN.Substring(0, fileN.Length - 4);
            List<string> childDirs = Directory.GetDirectories(dllPath).ToList().OrderByDescending(i => i).ToList();
            string re = @"/config/dlls/" + fileN + @"/" + Path.GetFileName(childDirs[0]) + @"/" + fileName;
            return re;
        }
        /// <summary>
        /// 上传dll时生成描述文件
        /// </summary>
        /// <param name="dllPath">dll文件保存的路径</param>
        /// <param name="versionNo">dll版本目录</param>
        /// <param name="describe">描述性内容</param>
        private void CreateDescribeFile(string dllPath, string versionNo, string describe)
        {
            // 如果没有描述性说明就不生成描述文件
            if (describe.Length > 0)
            {
                string desFile = dllPath + @"\" + versionNo + @"\describe.txt";
                if (System.IO.File.Exists(desFile))
                {
                    StreamWriter streamWriter = System.IO.File.AppendText(desFile);
                    streamWriter.WriteLine(describe);
                    streamWriter.Close();
                }
                else
                {
                    FileStream fileStream = new FileStream(desFile, FileMode.Create, FileAccess.Write);
                    StreamWriter streamWriter = new StreamWriter(fileStream);
                    streamWriter.WriteLine(describe);
                    streamWriter.Close();
                }
            }
        }
        /// <summary>
        /// 加密文件，输入源文件路径返回加密后文件路径
        /// </summary>
        /// <param name="inFileName">明文文件路径</param>
        /// <param name="outFileName">密文文件路径</param>
        private void EncryptFileToFile(string inFileName, string outFileName)
        {
            if (inFileName == outFileName)
            {
                string enFileName = Path.GetDirectoryName(inFileName) + "_" + Path.GetFileName(inFileName);
                FileSecret.EncryptFile(inFileName, enFileName);
                System.IO.File.Delete(inFileName);
                System.IO.File.Copy(enFileName, inFileName);
                System.IO.File.Delete(enFileName);
            }
            else
            {
                FileSecret.EncryptFile(inFileName, outFileName);
            }
        }

        /// <summary>
        /// 将文件信息存储到数据库中
        /// </summary>
        /// <param name="fullPath">文件路径</param>
        /// <param name="fileParentPath">文件路径</param>
        /// <param name="fileName">文件路径</param>
        /// <param name="explain">文件备注</param>
        private void SaveFileInfoToDb(string fullPath, string fileParentPath, string fileName, string explain)
        {
            DAL_ConfigFile dAL_ConfigFile = new DAL_ConfigFile();
            // 获取导航功能ID
            string configPath = fileParentPath;
            DAL_ProgramNavicat navicatDal = new DAL_ProgramNavicat();
            var programid = navicatDal.GetProgramId(configPath);
            // 现判断该文件是否存在
            string fileRelativePath = Path.Combine(fileParentPath, fileName).Replace("\\", @"/");
            int re = dAL_ConfigFile.ExistFile(fileRelativePath);
            if (re <= 0)
            {
                FileInfo fileInfo = new FileInfo(fullPath);
                string currentId = System.Guid.NewGuid().ToString("N");
                var parentConfig = dAL_ConfigFile.GetConfigFileByPath(fileParentPath);
                ConfigFiles model = new ConfigFiles();
                model.Currentid = currentId;
                model.Programid = programid;
                model.Parentid = parentConfig.Currentid;
                model.Level = parentConfig.Level + 1;
                model.Name = fileInfo.Name;
                model.Ctype = "F";
                model.Path = fileRelativePath;
                model.ParentPath = fileParentPath;
                model.Filesize = fileInfo.Length.ToString() + "B";
                model.Createdtime = fileInfo.CreationTime.ToString("yyyy-MM-dd HH:mm:ss");
                model.Updatetime = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss");
                model.Status = "1";
                model.Note = explain;
                dAL_ConfigFile.InsertConfig(model);
                #region 更新菜单统计数量
                var nav = navicatDal.GetNavicatById(programid);
                if (nav != null)
                {
                    DAL_MenuStatistics statisticsDal = new DAL_MenuStatistics();
                    //修改当前菜单文件数量
                    statisticsDal.FileNumIncremental(nav.Id);

                    //修改父级菜单文件数量
                    var allParentId = nav.AllParentId;
                    if (!string.IsNullOrWhiteSpace(allParentId))
                    {
                        List<string> parentids = allParentId.Split(",").Reverse().ToList();
                        foreach (var id in parentids)
                        {
                            long navId = Int64.Parse(id);
                            statisticsDal.FileNumIncremental(navId);
                        }
                    }
                }
                #endregion
            }
            else
            {
                dAL_ConfigFile.UpdateStamp(fileRelativePath);
            }
        }

        /// <summary>
        /// 刷新配置文件统计数量
        /// </summary>
        private void RefreshStatistics(string userName, string rid)
        {
            DAL_ConfigFile configFileDal = new DAL_ConfigFile();
            DAL_ProgramNavicat programNavicatDal = new DAL_ProgramNavicat();
            var configFileList = configFileDal.GetDeskStatistics();
            var desk = new
            {
                totalfilesnum = configFileList.TotalNum,
                processcfgfilesnum = configFileList.processCfgFilesNum,
                mlcfigfilenum = configFileList.MLCfigFileNum,
                modulecfgfilenum = configFileList.moduleCfgFileNum,
                todayaddfiles = configFileList.todayAddFiles
            };
            var navicats = programNavicatDal.GetProtramNavicatTree(userName, rid);
            var message = new { desk = desk, menus = navicats };
            var serializersettings = new JsonSerializerSettings
            {

                // 设置为驼峰命名

                ContractResolver = new CamelCasePropertyNamesContractResolver()

            };
            hubMessageServer.SendMessage(JsonConvert.SerializeObject(message, Newtonsoft.Json.Formatting.None, serializersettings));
        }

        /// <summary>
        /// 调整模块步骤编码
        /// </summary>
        private void UpdataModuelCode(List<ConfigFileInfoModel> configFiles)
        {
            List<string> editNames = new List<string> { "122.xml", "123.xml", "124.xml", "125.xml", "126.xml", "127.xml", "128.xml", "129.xml", "130.xml", "131.xml", "132.xml", "133.xml", "134.xml", "135.xml", "136.xml", "137.xml", "138.xml", "139.xml", "140.xml", "141.xml", "142.xml" };
            configFiles = configFiles.Where(x => x.parentPath.Replace("\\", "/") == "config/moduleconfig/analysismoduleconfig/2docsubsection")
                                     .Where(x=>editNames.Contains(x.name))
                                     .ToList();
            if(configFiles.Any())
            {
                foreach (var config in configFiles)
                {
                    string fileInfoFull = Path.Combine(configRootPath,config.parentPath, config.name).Replace("\\", "/");
                    FileInfo fileInfo = new FileInfo(fileInfoFull);
                    string xmlContent = FileSecret.DecryptFileToContent(fileInfoFull);
                    if (!string.IsNullOrWhiteSpace(xmlContent))
                    {
                        XDocument xdocument = XDocument.Parse(xmlContent);
                        var rootNode = xdocument.Element("root");
                        var stepList = rootNode.Descendants().Where(x => x.Name.LocalName == "step").ToList();
                        if (stepList != null && stepList.Any())
                        {
                            foreach (var step in stepList)
                            {
                                var oldCode= step.Attribute("code").Value;
                                if(!string.IsNullOrWhiteSpace(oldCode))
                                {
                                    step.Attribute("code").Value = oldCode.ToLower();
                                }
                            }
                        }

                        xdocument.Save(fileInfoFull);
                        this.EncryptFileToFile(fileInfoFull, fileInfoFull);
                    }
                }
            }
        }

        private void UpdataModuelRemark(List<ConfigFileInfoModel> configFiles)
        {
            foreach (var config in configFiles.Where(x=>string.IsNullOrWhiteSpace(x.note)))
            {
                var path = config.path;
                string fileInfoFull = Path.Combine(configRootPath, config.parentPath, config.name).Replace("\\", "/");
                string xmlContent = FileSecret.DecryptFileToContent(fileInfoFull);
                XDocument xdocument = XDocument.Parse(xmlContent);
                var rootNode = xdocument.Element("root");
                var remarkAttr = rootNode.Attribute("explain");
                if(remarkAttr!=null && !string.IsNullOrWhiteSpace(remarkAttr.Value))
                {
                    DAL_ConfigFile configFile = new DAL_ConfigFile();
                    configFile.UpdateNote(config.path, remarkAttr.Value);
                    config.note = remarkAttr.Value;
                }
            }
        }

        /// <summary>
        /// 修改卷宗分段配置文件的步骤编码（全部改为小写）
        /// </summary>
        private void EditDocsubsectionFile()
        {
            var dir = "config/moduleconfig/analysismoduleconfig/2docsubsection";
            var dirFullPath = Path.Combine(configRootPath, dir);
            DirectoryInfo directoryInfo = new DirectoryInfo(dirFullPath);
            if(directoryInfo.Exists)
            {
                var files = directoryInfo.GetFiles().Where(x => !x.Name.Contains("back") && !x.Name.Contains("index")).ToList();
                if(files!=null && files.Any())
                {
                    foreach (var fileInfo in files)
                    {
                        var fileInfoFull = fileInfo.FullName;
                        string xmlContent = FileSecret.DecryptFileToContent(fileInfoFull);
                        if (!string.IsNullOrWhiteSpace(xmlContent))
                        {
                            XDocument xdocument = XDocument.Parse(xmlContent);
                            var rootNode = xdocument.Element("root");
                            if(rootNode!=null)
                            {
                                var stepList = rootNode.Descendants().Where(x => x.Name.LocalName == "step").ToList();
                                if (stepList != null && stepList.Any())
                                {
                                    foreach (var step in stepList)
                                    {
                                        var oldCode = step.Attribute("code").Value;
                                        if (!string.IsNullOrWhiteSpace(oldCode))
                                        {
                                            step.Attribute("code").Value = oldCode.ToLower();
                                        }
                                    }
                                }

                                xdocument.Save(fileInfoFull);
                                this.EncryptFileToFile(fileInfoFull, fileInfoFull);
                            }
                            
                        }
                    }
                    
                }
            }
        }

    }
}
